﻿/*****
 *  Copyright 2011, Kaven Gagné
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using Knowledge.DataModel;
using System.Collections.ObjectModel;
using System.Windows;

namespace Knowledge
{
    public class ArticleViewModel : ViewModelBase
    {
        #region Constructors
        public ArticleViewModel(kArticle article, FolderViewModel parent) : base(parent, false)
        {
            _article = article;
        } 
        #endregion //Constructors

        #region Data
        private kArticle _article;
        private ObservableCollection<LinkViewModel> _links;
        private ObservableCollection<FileViewModel> _files;
        #endregion //Data



        
        #region Presentation Members

        #region ArticleID
        public int ArticleID
        {
            get
            {
                return _article.ArticleID;
            }
        } 
        #endregion //ArticleID

        #region ArticleName
        public String ArticleName
        {
            get
            {
                return _article.ArticleName;
            }
            set
            {
                _article.ArticleName = value;
                this.OnPropertyChanged("ArticleName");
            }
        } 
        #endregion //ArticleName

        #region Description
        public String Description
        {
            get
            {
                return _article.Description;
            }
            set
            {
                _article.Description = value;
                this.OnPropertyChanged("Description");
            }
        }
        #endregion //Description

        #region Links
        public ObservableCollection<LinkViewModel> Links
        {
            get { return _links; }
        } 
        #endregion //Links

        #region Files
        public ObservableCollection<FileViewModel> Files
        {
            get { return _files; }
        }
        #endregion //Files

        #region IsSelected
        public new bool IsSelected
        {
            get { return base.IsSelected; }
            set
            {
                if (value != base.IsSelected)
                {
                    base.IsSelected = value;
                    this.OnPropertyChanged("IsSelected");
                }
                // Expand all the way up to the root.
                //if (base.IsSelected && base.Parent != null)
                //    base.Parent.IsSelected = true;

                // Load the links for this Article
                this.LoadLinks();

                // Load the files for this Article (Not the FileData)
                this.LoadFiles();
            }
        } 
        #endregion //IsSelected

        #endregion //Presentation Members




        #region Public Methods

        #region LoadDescription
        public int LoadDescription()
        {
            int sts = 0;
            string desc = Database.GetDescription(_article, _article.ArticleID);
            if (desc == null)
            {
                // No description found, item might not exists
                sts = (int)Utilities.errCode.NO_ROW_AFFECTED;
                // Reload this Articles Parent Folder in TreeView
                ((FolderViewModel)this.Parent).LoadArticles();
            }
            else
            {
                this.Description = desc;
            }
            return sts;
        }
        #endregion //LoadDescription

        #region SaveDescription
        public int SaveDescription()
        {
            int sts = Database.SetDescription(_article, _article.ArticleID, this.Description);
            if (sts == (int)Utilities.errCode.NO_ROW_AFFECTED)
            {
                // Reload this Articles Parent Folder in TreeView
                ((FolderViewModel)this.Parent).LoadArticles();
            }
            return sts;
        }
        #endregion //SaveDescription

        #region AddLink
        public int AddLink(string name, string link)
        {
            int sts = Database.AddLink(name, link, _article.ArticleID);
            if (sts == (int)Utilities.errCode.NO_ROW_AFFECTED)
            {
                // Reload this Article's Parent Folder in TreeView
                ((FolderViewModel)this.Parent).LoadArticles();
            }
            else
            {
                // Reload the links for this Article
                this.LoadLinks();
            }
            return sts;
        } 
        #endregion //AddLink

        #region DeleteLinks
        public void DeleteLinks(List<LinkViewModel> links)
        {
            // ASK USER: are you sure that you want to delete those links?
            string msg = String.Format("Are you sure that you want to delete the following {0} links ?\n\n", links.Count);
            foreach (LinkViewModel link in links)
            {
                // Show all selected links
                msg += String.Format("{0} pointing to\n\t{1}\n", link.LinkName, link.LinkUri);
            }
            System.Media.SystemSounds.Exclamation.Play();
            MessageBoxResult res = MessageBox.Show(msg, String.Format("Delete {0} links ?", links.Count),
                                                   MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
            // User confirmed deletion
            if (res == MessageBoxResult.Yes)
            {
                foreach (LinkViewModel link in links)
                {
                    // Delete link from database
                    Database.DeleteLink(link.LinkID);
                }
                // Reload Links and Update Bindings
                this.LoadLinks();
            }
        }
        #endregion //DeleteLinks

        #region AddOrReplaceFile
        // Add or Replace file in the Database and Update Bindings
        public int AddOrReplaceFile(System.IO.FileInfo fInfo)
        {
            int sts = 0;
            // Is it larger than 30 MB?
            if (fInfo.Length > 30 * 1024 * 1024)
            {
                // Message USER: File is too big. Max size is 30 mb
                System.Media.SystemSounds.Exclamation.Play();
                MessageBox.Show(String.Format("The file {0} is too large. Maximum size is 30 MB... for now.", fInfo.FullName),
                                String.Format("File is too large [{0:F2} MB > 30 MB]", (double)fInfo.Length / 1024 / 1024));
            }
            // File Size OK
            else
            {
                // Search for same filename in current Article
                bool fileFound = false;
                int fileIndex = 0;
                foreach (FileViewModel file in this.Files)
                {
                    if (file.FileName.Equals(fInfo.Name))
                    {
                        fileFound = true;
                        break;
                    }
                    fileIndex++;
                }
                // File Exists in Same Article
                if (fileFound)
                {
                    // ASK USER to Replace file
                    System.Media.SystemSounds.Exclamation.Play();
                    MessageBoxResult replaceFile =
                            MessageBox.Show(String.Format(
                                                "A file named {0} already exist in the same Article.\n" +
                                                "Do you want to replace it ?", fInfo.Name),
                                            "Replace Existing File With New One?",
                                            MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
                    // Agree to replace
                    if (replaceFile == MessageBoxResult.Yes)
                    {
                        // Replace file in the database
                        // IF no error occurs
                        sts = Database.ReplaceFile(fInfo, _files[fileIndex].FileID);
                        if (sts == (int)Utilities.errCode.NO_ROW_AFFECTED)
                        {
                            // Reload this Article's Parent Folder in TreeView
                            ((FolderViewModel)this.Parent).LoadArticles();
                        }
                        else
                        {
                            // Reload the files for this Article
                            this.LoadFiles();
                        }
                    }
                }
                // File does not exist in DB
                else
                {
                    // Add the file to the DB
                    // IF no error occurs
                    sts = Database.AddFile(fInfo, _article.ArticleID);
                    if (sts == (int)Utilities.errCode.FOREIGN_KEY_CONSTRAINT)
                    {
                        // Reload this Article's Parent Folder in TreeView
                        ((FolderViewModel)this.Parent).LoadArticles();
                    }
                    else
                    {
                        // Reload the files for this Article
                        this.LoadFiles();
                    }
                }
            }
            return sts;
        }
        #endregion //AddOrReplaceFile

        #region DeleteFile
        public void DeleteFile(FileViewModel file)
        {
            // ASK USER do you really want to delete ?
            System.Media.SystemSounds.Exclamation.Play();
            MessageBoxResult deleteFile =
                    MessageBox.Show(String.Format("Are you sure that you want to delete {0} from the database ?", file.FileName),
                                    "Delete File ?",
                                    MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
            // Delete confirmed
            if (deleteFile == MessageBoxResult.Yes)
            {
                Database.DeleteFile(file.FileID);
                this.LoadFiles();
            }
        } 
        #endregion //DeleteFile

        #endregion //Public Methods




        #region Private Methods

        #region LoadLinks
        // Load the links from the database and Update Bindings
        private void LoadLinks()
        {
            List<kLink> links = Database.GetLinks(_article.ArticleID);
            _links = new ObservableCollection<LinkViewModel>(
                (from link in links select new LinkViewModel(link, this)).ToList()
            );
            this.OnPropertyChanged("Links");
        } 
        #endregion //LoadLinks

        #region LoadFiles
        // Load the files from the database and Update Bindings
        public void LoadFiles()
        {
            // Load the files for this Article (Not the FileData)
            List<kFile> files = Database.GetFiles(_article.ArticleID);
            _files = new ObservableCollection<FileViewModel>(
                (from file in files select new FileViewModel(file, this)).ToList()
            );
            this.OnPropertyChanged("Files");
        } 
        #endregion //LoadFiles

        #endregion //Private Methods




        #region Overrides
        protected override void LoadChildren()
        {
        }
        #endregion //Overrides
    }
}
